Homelab Deployment
This guide builds on the Quick Start and covers the choices that matter for a long-running home server: storage, networking, TLS, permissions, and monitoring.
Recommended Layout
Use separate storage for the PostgreSQL database, working directories, and published media when possible:
Fast local disk
├── PostgreSQL volume
├── inbound
├── staging
└── logs
Capacity storage or NAS
├── storage
├── podcasts
├── playlists
├── themes
└── templates
The default Compose deployment uses named volumes. A
compose.override.yml can bind existing host directories to the container:
services:
melodee.blazor:
volumes:
- /srv/melodee/inbound:/app/inbound
- /srv/melodee/staging:/app/staging
- /mnt/music:/app/storage
- /srv/melodee/podcasts:/app/podcasts
Avoid mounting Inbound, Staging, and Storage on the same directory. Melodee moves and rewrites files while processing, so overlapping roots can cause reprocessing or data loss.
For NFS or SMB storage, mount the share on the host first and bind that host mount into the container. Store SMB credentials in a root-readable credentials file rather than placing a password directly in shell history or Compose YAML.
Network Exposure
The supplied Compose file publishes MELODEE_PORT (default 8080) on all host
interfaces. For a LAN-only installation, restrict access with the host firewall.
For internet access, place Melodee behind a TLS-terminating reverse proxy and do
not expose PostgreSQL.
After configuring the proxy, set system.baseUrl under Admin > Settings to
the external origin, for example https://music.example.com. Do not include a
trailing API path.
Nginx Example
Blazor Server and Party Mode use upgraded connections, while audio streaming benefits from disabled proxy buffering:
server {
listen 443 ssl;
server_name music.example.com;
ssl_certificate /etc/letsencrypt/live/music.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/music.example.com/privkey.pem;
client_max_body_size 100m;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
proxy_read_timeout 3600s;
}
}
Melodee enables forwarded-header processing by default. Keep the application reachable only through a trusted proxy when relying on forwarded client addresses.
Traefik Labels
services:
melodee.blazor:
labels:
- "traefik.enable=true"
- "traefik.http.routers.melodee.rule=Host(`music.example.com`)"
- "traefik.http.routers.melodee.entrypoints=websecure"
- "traefik.http.routers.melodee.tls=true"
- "traefik.http.services.melodee.loadbalancer.server.port=8080"
Container Resources
The supplied Compose file caps the application at one CPU and 2 GB of memory.
That is adequate for initial evaluation but can constrain large scans,
transcoding, or multiple streams. Adjust the deploy.resources.limits values in
an override after observing the host; do not remove limits on a shared machine
without monitoring.
Keep the PostgreSQL volume on low-latency storage. Media can live on slower or network storage, but scans and imports will be limited by that storage’s random I/O and metadata performance.
See Hardware & Performance for starting points.
Rootless Podman and Permissions
The setup helper includes a permissions diagnostic:
python3 scripts/run-container-setup.py --check-permissions
For bind mounts, ensure the mapped container process can traverse every parent directory and write the Inbound, Staging, Storage, podcast, theme, and template paths. Prefer narrowly scoped ownership or ACLs over world-writable modes.
Audio Output and Jukebox
The published image includes ffmpeg, but it does not install MPV or MPD or
automatically expose host audio devices. Server-side Jukebox
therefore requires a custom image or a separately reachable MPD instance, plus
explicit audio-device access. Ordinary browser and API streaming does not need
host audio hardware.
Monitoring
docker compose ps
docker compose logs --tail=200 melodee.blazor
docker compose logs --tail=100 melodee-db
docker stats
curl --fail http://localhost:8080/health
The /health endpoint is the container liveness/readiness probe. Use
Admin > Doctor for deeper checks such as library paths, required tools,
DecentDB compatibility, search-provider credentials, and writable storage.
Monitor at least:
- Free space on the database, Inbound, Staging, Storage, and backup filesystems
- Application restarts and unhealthy container states
- PostgreSQL backup completion and restore tests
- Scan duration, transcoding CPU use, and application log growth
Routine Operations
- Back up PostgreSQL and persistent application volumes before upgrades.
- Pin release images instead of relying on
latestfor unattended updates. - Review release notes before changing versions.
- Keep the proxy, container runtime, host kernel, and PostgreSQL image patched.
- Test restores on a separate host or isolated Compose project.
See Backup & Recovery and Upgrade Guide for executable procedures.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.